/*
 *
 *  ------------------------------------------------------------------
 *  Copyright © 2017 Hangzhou DtDream Technology Co.,Lt d. All rights reserved.
 *  ------------------------------------------------------------------
 *        Product:  EMR
 *    Module Name: NEZHA
 *   Date Created: 17-10-23 下午4:22
 *    Description:
 *  ------------------------------------------------------------------
 *  Modification History
 *  DATE            Name           Description
 *  ------------------------------------------------------------------
 *  2017-10-23      NEZHA EMR
 *  ------------------------------------------------------------------
 * /
 */

package org.xukai.remoting.sdk.web;


import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public interface SQLClient extends AutoCloseable {

    /**
     * Executes one {@code sql} string.
     *
     * @param sql
     * @throws SQLException
     */
    void execute(String sql) throws SQLException;

    /**
     * Executes one {@code sql} string and returns query result.
     *
     * @param sql
     * @return Query result
     * @throws SQLException
     */
    SQLResult executeQuery(String sql) throws SQLException;

    /**
     * Executes a sql batch and returns query result of sqls.
     *
     * @param sqls
     * @return a {@link SQLResult} list in {@code sqls} order.
     * @throws SQLException
     */
    List<SQLResult> executeBatch(List<String> sqls) throws SQLException;

    /**
     * Adds a file to be downloaded with next sql on every Spark node.
     * {@code path} must be accessible to Spark Thrift Server.
     *
     * @param path file path, usually an hdfs url.
     * @throws SQLException
     */
    void addFile(String path) throws SQLException;

    /**
     * Adds a jar to be downloaded with next sql on every Spark node. Jar will also be added to classpath on every Spark node.
     * {@code path} must be accessible to Spark Thrift Server.
     *
     * @param path file path, usually an hdfs url.
     * @throws SQLException
     */
    void addJar(String path) throws SQLException;

    /**
     * Deletes a jar from SparkContext.
     *
     * @param path
     * @throws SQLException
     */
    void deleteJar(String path) throws SQLException;

    /**
     * Creates a table using {@link String}.
     *
     * @param tableName
     * @param schemaStr
     * @throws SQLException
     */
    void createTable(String tableName, String schemaStr) throws SQLException;

    /**
     * Creates a table using {@link TableSchema}.
     *
     * @param tableName
     * @param schema
     * @throws SQLException
     */
    void createTable(String tableName, TableSchema schema) throws SQLException;

    /**
     * Drops a table.
     *
     * @param tableName
     * @throws SQLException
     */
    void dropTable(String tableName) throws SQLException;

    /**
     * Truncates a table.
     *
     * @param tableName
     * @throws SQLException
     */
    void truncateTable(String tableName) throws SQLException;

    /**
     * Creates a permanent UDF.
     *
     * @param funcName
     * @param className
     * @throws SQLException
     */
    void addFunction(String funcName, String className) throws SQLException;

    /**
     * Creates a permanent UDF and records the jar file path.
     *
     * @param funcName
     * @param className
     * @param jarPath
     * @throws SQLException
     */
    void addFunction(String funcName, String className, String jarPath) throws SQLException;

    /**
     * Drops an UDF.
     *
     * @param funcName
     * @throws SQLException
     */
    void dropFunction(String funcName) throws SQLException;

    /**
     * Shows a table's partitions.
     *
     * @param tableName
     * @return
     * @throws SQLException
     */
    SQLResult showPartitions(String tableName) throws SQLException;

    /**
     * Shows a table's partitions specified by {@code partSpec}
     *
     * @param tableName
     * @param partSpec  partition column name and value pairs.
     * @return
     * @throws SQLException
     */
    SQLResult showPartitions(String tableName, Map<String, String> partSpec) throws SQLException;

    /**
     * Creates a table partition.
     *
     * @param tableName
     * @param partition a Map contains one partition's column and value pairs.
     * @throws SQLException
     */
    void createPartition(String tableName, Map<String, String> partition) throws SQLException;

    /**
     * Drops a table partition.
     *
     * @param tableName
     * @param partition a Map contains one partition's column and value pairs.
     * @throws SQLException
     */
    void dropPartition(String tableName, Map<String, String> partition) throws SQLException;

    /**
     * Truncates a table partition.
     *
     * @param tableName
     * @param partition
     * @throws SQLException
     */
    void truncatePartition(String tableName, Map<String, String> partition) throws SQLException;

    /**
     * Get the names of all tables in current database.
     *
     * @return
     * @throws SQLException
     */
    List<String> getAllTableNames() throws SQLException;

    /**
     * Retrieves the table types available in this database.
     * For now, available table types are "TABLE" and "VIEW".
     *
     * @return
     */
    List<String> getTableTypes() throws SQLException;

    /**
     * Retrieves table names in the given database.
     *
     * @param tablePattern a table name pattern; {@code null} or empty string means that the table name should not
     *                     be used to narrow the search.
     *                     Wildcards in the pattern can only be '*' for any character(s) or '|' for a choice.
     *                     Examples are 'employees', 'emp*', 'emp*|*ees', all of which will match the database named 'employees'.
     * @param tableType    a table type, which must be from the list of table types returned from {@link #getTableTypes};
     *                     returns tables of all types if no ${@code tableType} parameter is given
     * @return
     * @throws SQLException
     * @see <a href="https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-ShowTables">
     * LanguageManualDDL-ShowTables</a> to find supported table name patterns
     */
    List<String> getTableNames(String tablePattern, String... tableType) throws SQLException;

    /**
     * Shows all table descriptions in current database.
     *
     * @return
     * @throws SQLException
     */
    @Deprecated
    List<TableDesc> getTables() throws SQLException;


    /**
     * Retrieves table descriptions in the given database.
     *
     * @param tablePattern a table name pattern; {@code null} or empty string means that the table name should not
     *                     be used to narrow the search.
     *                     Wildcards in the pattern can only be '*' for any character(s) or '|' for a choice.
     *                     Examples are 'employees', 'emp*', 'emp*|*ees', all of which will match the database named 'employees'.
     * @param tableType    a table type, which must be from the list of table types returned from {@link #getTableTypes};
     *                     returns tables of all types is no ${@code tableType} parameter is given
     * @return
     * @throws SQLException
     * @see <a href="https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-ShowTables">
     * LanguageManualDDL-ShowTables</a> to find supported table name patterns
     */
    @Deprecated
    List<TableDesc> getTables(String tablePattern, String... tableType) throws SQLException;

    /**
     * Retrieves table descriptions in the given database.
     *
     * @param pageNum
     * @param pageSize
     * @param tablePattern a table name pattern; {@code null} or empty string means that the table name should not
     *                     be used to narrow the search.
     *                     Wildcards in the pattern can only be '*' for any character(s) or '|' for a choice.
     *                     Examples are 'employees', 'emp*', 'emp*|*ees', all of which will match the database named 'employees'.
     * @param tableType    a table type, which must be from the list of table types returned from {@link #getTableTypes};
     *                     returns tables of all types is no ${@code tableType} parameter is given
     * @return
     * @throws SQLException
     * @see <a href="https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-ShowTables">
     * LanguageManualDDL-ShowTables</a> to find supported table name patterns
     */
    Page<TableDesc> getTables(int pageNum, int pageSize, String tablePattern, String... tableType) throws SQLException;

    /**
     * Describes a table in detail.
     *
     * @param tableName
     * @return
     * @throws SQLException
     */
    TableDetail getTableDetail(String tableName) throws SQLException;

    /**
     * Shows the detail about the current database.
     *
     * @param databaseName
     * @return
     * @throws SQLException
     */
    DatabaseDetail getDatabaseDetail(String databaseName) throws SQLException;

    /**
     * Selects all records in a table. Equals to "select * from {@code tableName}".
     *
     * @param tableName
     * @return
     * @throws SQLException
     */
    @Deprecated
    SQLResult getTableRecord(String tableName) throws SQLException;

    /**
     * Selects records in a table with limit. Equals to "select * from {@code tableName} limit {@code limit}".
     *
     * @param tableName
     * @param limit
     * @return
     * @throws SQLException
     */
    @Deprecated
    SQLResult getTableRecord(String tableName, int limit) throws SQLException;

    /**
     * Selects records were authorized in a table. Equals to "select {@code columns} from {@code tableName}".
     *
     * @param tableName
     * @param columns
     * @return
     * @throws SQLException
     */
    SQLResult getTableRecord(String tableName, String[] columns) throws SQLException;

    /**
     * Selects records were authorized in a table with limit.
     * Equals to "select {@code columns} from {@code tableName} limit {@code limit}".
     *
     * @param tableName
     * @param limit
     * @return
     * @throws SQLException
     */
    SQLResult getTableRecord(String tableName, String[] columns, int limit) throws SQLException;

    /**
     * Refreshes {@code tableName}'s data and metadata in Spark Thrift Server.
     *
     * @param tableName
     * @throws SQLException
     */
    void refreshTable(String tableName) throws SQLException;

    /**
     * Submits a SQL Job Batch containing one sql to NeZha Server and returns a JobID.
     *
     * @param sql
     * @return
     * @throws SQLException
     */
    String submitJob(String sql) throws SQLException;

    /**
     * Submits a SQL Job Batch to NeZha Server and returns a JobID.
     *
     * @param sqls
     * @return
     * @throws SQLException
     */
    String submitJob(List<String> sqls) throws SQLException;

    /**
     * Gets a SQL Job executing progress.
     *
     * @param jobId
     * @return a {@link SQLJobReport} instance. Each sql's progress can be got in {@link SQLJobReport#getStmtReports()}
     * @throws SQLException
     */
    SQLJobReport progress(String jobId) throws SQLException;

    /**
     * Fetches a sql's result.
     *
     * @param jobId
     * @param stmtIndex index of sql in submitted sql list.
     * @return
     * @throws SQLException
     */
    SQLResult fetchSQLResult(String jobId, int stmtIndex) throws SQLException;

    /**
     * Fetches a sql's log.
     *
     * @param jobId
     * @param stmtIndex index of sql in submitted sql list.
     * @return
     * @throws SQLException
     */
    SQLLog fetchSQLLog(String jobId, int stmtIndex) throws SQLException;

    /**
     * Fetches a {@link SQLTracker} to track statement progress.
     *
     * @param jobId
     * @param stmtIndex index of sql in submitted sql list.
     * @return
     * @throws SQLException
     */
    SQLTracker fetchSQLTracker(String jobId, int stmtIndex) throws SQLException;

    /**
     * Asks NeZha Server to cancel a SQL Job. Cancel operation is asynchronous.
     *
     * @param jobId
     * @throws SQLException
     */
    void cancelJob(String jobId) throws SQLException;

    /**
     * No need to call {@link #close()} anymore.
     *
     * @throws SQLException
     * @deprecated Will be removed in next version.
     */
    @Deprecated
    void close() throws SQLException;
}
